﻿// //   Copyright 2007-2011 Comdiv (F. Sadykov) - http://code.google.com/u/fagim.sadykov/
// //   Supported by Media Technology LTD 
// //    
// //   Licensed under the Apache License, Version 2.0 (the "License");
// //   you may not use this file except in compliance with the License.
// //   You may obtain a copy of the License at
// //    
// //        http://www.apache.org/licenses/LICENSE-2.0
// //    
// //   Unless required by applicable law or agreed to in writing, software
// //   distributed under the License is distributed on an "AS IS" BASIS,
// //   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// //   See the License for the specific language governing permissions and
// //   limitations under the License.
// //   
// //   MODIFICATIONS HAVE BEEN MADE TO THIS FILE

using System;
using System.Xml.Linq;
using Comdiv.QWeb.Cache;
using Comdiv.QWeb.Events;
using Comdiv.QWeb.Files;
using Comdiv.QWeb.Serialization.Attributes;
using Comdiv.QWeb.Utils;

namespace Comdiv.QWeb {
	public abstract class ActionBase : IContextualAction, INotModifiedStateProvider, IRegistryBound {
		private string _etag;
		private DateTime _lastmodified;
		private QWebServiceRegistry _registry;
		private bool? _supportnmd;
		protected QWebContext Context;

		protected ActionBase() {
			var qatr = GetType().getFirstAttribute<ActionAttribute>();
			if (null != qatr && qatr.Role.hasContent()) {
				Role = qatr.Role;
			}
			else {
				Role = "DEFAULT";
			}
		}

		public string Role { get; set; }

		protected IFileNameResolver FileNameResolver {
			get { return Context.Registry.FileNameResolver; }
		}

		#region IContextualAction Members

		public object Process(QWebContext ctx) {
			Context = ctx;
			initialize();
			validate();
			prepare();
			authorize();
			return process();
		}

		public virtual void SetContext(QWebContext context) {
			defaultSetContext(context);
		}

		#endregion

		#region INotModifiedStateProvider Members

		[IgnoreSerialize] public DateTime LastModified {
			get {
				if (_lastmodified == DateTime.MinValue) {
					_lastmodified = new DateTime(1900, 1, 1);
					if (SupportNotModifiedState) {
						_lastmodified = evalLastModified();
						_lastmodified = new DateTime(_lastmodified.Year, _lastmodified.Month, _lastmodified.Day, _lastmodified.Hour,
						                             _lastmodified.Minute, _lastmodified.Second);
					}
				}
				return _lastmodified;
			}
			set { _lastmodified = new DateTime(value.Year, value.Month, value.Day, value.Hour, value.Minute, value.Second); }
		}

		[IgnoreSerialize] public string ETag {
			get {
				if (_etag == null) {
					_etag = "";
					if (SupportNotModifiedState) {
						_etag = evalEtag();
					}
				}
				return _etag;
			}
			set { _etag = value; }
		}

		public bool SupportNotModifiedState {
			get {
				if (_supportnmd == null) {
					_supportnmd = false;
					_supportnmd = getSupportNotModified();
				}
				return _supportnmd.Value;
			}
		}

		#endregion

		#region IRegistryBound Members

		public QWebServiceRegistry Registry {
			get { return _registry; }
		}

		public void SetRegistry(QWebServiceRegistry registry) {
			_registry = registry;
			onSetRegistry();
		}

		#endregion

		protected bool IsInRole(string role, bool exact = false) {
			return Context.Registry.RoleResolver.IsInRole(Context.Registry.PrincipalSource.CurrentUser, role, exact, Context);
		}

		protected T OnApplication<T>() where T : IQWebEvent, new() {
			return Context.Registry.Events.OnApplication<T>(Context).Invoke();
		}

		protected T OnThread<T>() where T : IQWebEvent, new() {
			return Context.Registry.Events.OnThread<T>(Context).Invoke();
		}

		protected string ResolveFileName(string name, bool existed = true,
		                                 FileResolveResultType resolvetype = FileResolveResultType.FullPath) {
			return FileNameResolver.Resolve(Context, resolvetype, existed, null, new[] {name}, Context.Registry.Log);
		}

		protected void defaultSetContext(QWebContext context) {
			this.Context = context;
			_lastmodified = new DateTime();
			_etag = null;
			_supportnmd = null;
		}

		protected virtual T get<T>(string name, T def = default(T)) {
			return Context.get(name, def);
		}

		protected virtual string get(string name, string def = "") {
			return Context.get(name, def);
		}

		protected virtual XElement getx(string name) {
			return Context.getx(name);
		}

		protected virtual void initialize() {
		}

		protected virtual void validate() {
		}

		protected virtual void prepare() {
		}

		protected virtual void authorize() {
		}

		protected virtual object process() {
			return null;
		}

		protected virtual DateTime evalLastModified() {
			return new DateTime(1900, 1, 1);
		}

		protected virtual string evalEtag() {
			return "";
		}

		protected virtual bool getSupportNotModified() {
			return false;
		}

		protected virtual void onSetRegistry() {
		}

		public object Process() {
			return Process(Context);
		}
	}
}